package com.xianniu.ltc.controller;

import cn.devezhao.bizz.privileges.DepthEntry;
import cn.devezhao.bizz.privileges.Privileges;
import cn.devezhao.bizz.privileges.impl.BizzDepthEntry;
import cn.devezhao.bizz.privileges.impl.BizzPermission;
import cn.devezhao.bizz.security.member.BusinessUnit;
import cn.devezhao.bizz.security.member.NoMemberFoundException;
import cn.devezhao.bizz.security.member.Role;
import cn.devezhao.persist4j.engine.ID;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rebuild.core.Application;
import com.rebuild.core.privileges.DepartmentService;
import com.rebuild.core.privileges.UserHelper;
import com.rebuild.core.privileges.UserService;
import com.rebuild.core.privileges.bizz.Department;
import com.rebuild.core.privileges.bizz.User;
import com.rebuild.web.BaseController;
import com.xianniu.ltc.enums.NicheWinRate;
import com.xianniu.ltc.mapper.*;
import com.xianniu.ltc.model.entity.*;
import com.xianniu.ltc.model.vo.FinancialStatisticsVO;
import com.xianniu.ltc.model.vo.NicheStatisticsVO;
import com.xxl.sso.core.entity.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商机控制器
 * @Author: dingyx
 * @Date: 2022/2/28 10:37 上午
 */
@RestController
@Slf4j
@RequestMapping(value = "/niche")
public class NicheController extends BaseController {
    @Resource
    private TRbhetong0Mapper tRbhetong0Mapper;
    @Resource
    private THuikuanjihuaMapper tHuikuanjihuaMapper;
    @Resource
    private THuikuandanMapper tHuikuandanMapper;
    @Resource
    private TKaipiaoguanliMapper tKaipiaoguanliMapper;
    @Resource
    private RbShangjiMapper rbShangjiMapper;
    /**
     * 商机实体编号
     */
    private final static Integer NICHE_CODE = 991;
    /**
     * 销售合同
     */
    private final static Integer CONTACT_CODE = 992;
    /**
     * 查询商机列表
     * @param request
     * @return
     */
    @PostMapping("/list")
    public ReturnT nicheList(HttpServletRequest request, @RequestBody JSONObject jsonObject) {
        final ID userId = getRequestUser(request);
        User user = Application.getUserStore().getUser(userId);
        Role role = user.getOwningRole();
        Privileges ep = role.getPrivileges(NICHE_CODE);
        log.info("当前用户{}对商机的权限：{}", userId, JSONObject.toJSONString(ep));
        DepthEntry de = ep.superlative(BizzPermission.READ);
        log.info("当前用户{}对商机的读取权限：{}", userId, JSONObject.toJSONString(de));
        // 当前用户所在部门
        Department dept = UserHelper.getDepartment(userId);
        // 坐在部门的所有子部门
        Set<BusinessUnit> units = dept.getAllChildrenModified();
        units.add(dept);
        // 查询该组织下的所有商机统计信息
        QueryWrapper<TRbshangji4DTO> queryWrapper = new QueryWrapper<>();
        if(BizzDepthEntry.PRIVATE.equals(de)){
            queryWrapper.eq("OWNING_USER", userId.toString());
        }else if(BizzDepthEntry.LOCAL.equals(de)){
            queryWrapper.eq("OWNING_DEPT", dept.getIdentity().toString());
        }else if(userId.equals(UserService.ADMIN_USER)  || BizzDepthEntry.GLOBAL.equals(de)){
        }else if(BizzDepthEntry.DEEPDOWN.equals(de)){
            queryWrapper.in("OWNING_DEPT", units.stream().map(unit -> unit.getIdentity().toString()).collect(Collectors.toList()));
        }else{
            log.error("该用户在实体{}配置了错误的权限{}", NICHE_CODE, de);
        }
        // 根据条件查询商机列表
        List<TRbshangji4DTO> deptValue = rbShangjiMapper.selectList(queryWrapper);

        // 当前年份
        int nowYear = DateUtil.year(new Date());
        // 排除 商机输单 且最后修改日期是 不是当前年份
        List<TRbshangji4DTO> loseList = deptValue.
                stream().
                filter(
                        ca -> NicheWinRate.loseCase().contains(ca.getShangjijieduanyinglv())
                ).
                filter(
                        ca ->  nowYear != DateUtil.year(ca.getModifiedOn())
                ).
                collect(Collectors.toList());
        // 排除 商机赢单 且预计日期是 不是当前年份
        List<TRbshangji4DTO> winList = deptValue.
                stream().
                filter(
                        ca -> NicheWinRate.winCase().contains(ca.getShangjijieduanyinglv())
                ).
                filter(
                        ca ->  (Objects.nonNull(ca.getShangjiyingdanshijian()) && nowYear != DateUtil.year(ca.getShangjiyingdanshijian())) || Objects.isNull(ca.getShangjiyingdanshijian())
                ).
                collect(Collectors.toList());
        deptValue.removeAll(loseList);
        deptValue.removeAll(winList);
        // 商机列表根据所属部门分组
        Map<String, List<TRbshangji4DTO>> deptMaps  = deptValue.stream().collect(Collectors.groupingBy(TRbshangji4DTO::getOwningDept, Collectors.toList()));
        // 清洗部门数据
        List<NicheStatisticsVO> result = getNicheStatisticsVOS(deptMaps);
        List<NicheStatisticsVO> response = getNicheStatisticsVOS(result);
        return new ReturnT(response);
    }

    @NotNull
    private List<NicheStatisticsVO> getNicheStatisticsVOS(List<NicheStatisticsVO> result) {
        /*** test start ***/
        List<NicheStatisticsVO> response = new ArrayList<>();
        add(response, result.stream().filter(niche -> niche.getOwnerDept().equalsIgnoreCase("总经办")).findAny().orElse(null));
        cleanChild(result, getDeptName("业务拓展部"));
        cleanChild(result, getDeptName("区域销售平台"));
        add(response, cleanChild(result, getDeptName("销售中心")));
        add(response, cleanChild(result, getDeptName("共享服务中心")));
        cleanChild(result, getDeptName("交付部门（DC）"));
        cleanChild(result, getDeptName("交付部门（IOT）"));
        cleanChild(result, getDeptName("交付资源池"));
        add(response, cleanChild(result, getDeptName("交付中心")));
        //
        NicheStatisticsVO topDept = cleanChild(result, getDeptName("总经办"));
        if(Objects.nonNull(topDept) && CollectionUtils.isNotEmpty(topDept.getChildren())){
            List<NicheStatisticsVO> children = topDept.getChildren();
            add(response, children.stream().filter(niche -> niche.getOwnerDept().equalsIgnoreCase("云原生")).findAny().orElse(null));
            add(response, children.stream().filter(niche -> niche.getOwnerDept().equalsIgnoreCase("业务产品部")).findAny().orElse(null));
            add(response, children.stream().filter(niche -> niche.getOwnerDept().equalsIgnoreCase("供应链采购部门")).findAny().orElse(null));
            add(response, children.stream().filter(niche -> niche.getOwnerDept().equalsIgnoreCase("仓储部门")).findAny().orElse(null));
            add(response, children.stream().filter(niche -> niche.getOwnerDept().equalsIgnoreCase("技术部")).findAny().orElse(null));
        }
        /*** test end ***/
        return response;
    }

    void add(List<NicheStatisticsVO> response, NicheStatisticsVO niche){
        if(Objects.nonNull(niche)){
            response.add(niche);
        }
    }

    private BusinessUnit getDeptName(String deptName){
        // 跟部门
        Department dept = Application.getUserStore().getDepartment(DepartmentService.ROOT_DEPT);
        // 坐在部门的所有子部门(包括自己)
        Set<BusinessUnit> units = dept.getAllChildrenModified();
        units.add(dept);
        BusinessUnit result = null;
        for(BusinessUnit unit : units){
            if(unit.getName().equals(deptName)){
                result = unit;
                break;
            }
        }
        if(Objects.isNull(result)){
            log.info("搜索部门{}不存在", deptName);
        }else{
            log.info("搜索部门是{}", deptName);
        }
        return result;
    }

    private NicheStatisticsVO cleanChild(List<NicheStatisticsVO> result, BusinessUnit markDept) {
        NicheStatisticsVO area = new NicheStatisticsVO();
        if(Objects.isNull(markDept)){
            log.info("日，部门是空的");
            return null;
        }
        NicheStatisticsVO temp = result.stream().filter(niche -> niche.getOwnerDept().equalsIgnoreCase(markDept.getName())).findAny().orElse(null);

        if(Objects.nonNull(temp)){
            log.info("列表中可以找到{}部门的商机", markDept.getName());
            BeanUtils.copyProperties(temp, area);
            result.remove(temp);
        }else{
            log.info("列表中可以找不到{}部门的商机", markDept.getName());
            area.setOwnerDept(markDept.getName());
            area.setOwnerDeptId(markDept.getIdentity().toString());
            if(Objects.isNull(markDept.getParent())){
                area.setParentDeptId("");
            }else{
                area.setParentDeptId(markDept.getParent().getIdentity().toString());
            }
        }
        result.add(area);
        List<NicheStatisticsVO> areaChildren = result.stream().filter(niche -> niche.getParentDeptId().equalsIgnoreCase(area.getOwnerDeptId())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(areaChildren)) {
            log.info("部门{}可以根据部门id{}匹配到子项", area.getOwnerDept(), area.getOwnerDeptId());
            area.setChildren(areaChildren);
            area.setNicheNumber(area.getNicheNumber().intValue() + areaChildren.stream().mapToInt(NicheStatisticsVO::getNicheNumber).sum());
            area.setWinNicheNumber(area.getWinNicheNumber().intValue() + areaChildren.stream().mapToInt(NicheStatisticsVO::getWinNicheNumber).sum());
            area.setWinNicheAmount(NumberUtil.add(area.getWinNicheAmount(), areaChildren.stream().map(NicheStatisticsVO::getWinNicheAmount).reduce(BigDecimal.ZERO, BigDecimal::add)));
            area.setLooseNicheNumber(area.getLooseNicheNumber().intValue() + areaChildren.stream().mapToInt(NicheStatisticsVO::getLooseNicheNumber).sum());
            area.setLooseNicheAmount(NumberUtil.add(area.getLooseNicheAmount(), areaChildren.stream().map(NicheStatisticsVO::getLooseNicheAmount).reduce(BigDecimal.ZERO, BigDecimal::add)));
            area.setNicheAmountWinRate60_90(NumberUtil.add(area.getNicheAmountWinRate60_90(), areaChildren.stream().map(NicheStatisticsVO::getNicheAmountWinRate60_90).reduce(BigDecimal.ZERO, BigDecimal::add)));
            area.setNicheNumberWinRate60_90(area.getNicheNumberWinRate60_90().intValue() + areaChildren.stream().mapToInt(NicheStatisticsVO::getNicheNumberWinRate60_90).sum());
            area.setNicheAmountWinRate10_50(NumberUtil.add(area.getNicheAmountWinRate10_50(), areaChildren.stream().map(NicheStatisticsVO::getNicheAmountWinRate10_50).reduce(BigDecimal.ZERO, BigDecimal::add)));
            area.setNicheNumberWinRate10_50(area.getNicheNumberWinRate10_50().intValue() + areaChildren.stream().mapToInt(NicheStatisticsVO::getNicheNumberWinRate10_50).sum());
            area.setNicheAmountWinRate10_90(NumberUtil.add(area.getNicheAmountWinRate10_90(), areaChildren.stream().map(NicheStatisticsVO::getNicheAmountWinRate10_90).reduce(BigDecimal.ZERO, BigDecimal::add)));
            area.countAmount();
            log.info("--->部门：{}下的商机信息是：{}", markDept.getName(), JSONArray.toJSONString(areaChildren));
            return area;
        }else{
            log.info("根据部门id{}无法匹配到子项", area.getOwnerDeptId());
            return null;
        }
    }

    @PostMapping("/listBySaleMan")
    public ReturnT listBySaleMan(HttpServletRequest request, @RequestBody JSONObject jsonObject) {
        // 筛选的部门
        String deptID = jsonObject.getString("deptId");
        final ID userId = getRequestUser(request);
        User user = Application.getUserStore().getUser(userId);
        Role role = user.getOwningRole();
        Privileges ep = role.getPrivileges(NICHE_CODE);
        DepthEntry de = ep.superlative(BizzPermission.READ);
        // 当前用户所在部门
        Department dept = UserHelper.getDepartment(userId);
        // 坐在部门的所有子部门
        Set<BusinessUnit> units = dept.getAllChildrenModified();
        units.add(dept);
        // 查询该组织下的所有商机统计信息
        QueryWrapper<TRbshangji4DTO> queryWrapper = new QueryWrapper<>();
        if(BizzDepthEntry.PRIVATE.equals(de)){
            queryWrapper.eq("OWNING_USER", userId.toString());
        }else if(BizzDepthEntry.LOCAL.equals(de)){
            queryWrapper.eq("OWNING_DEPT", dept.getIdentity().toString());
        }else if(userId.equals(UserService.ADMIN_USER)  || BizzDepthEntry.GLOBAL.equals(de)){
            if(StrUtil.isNotBlank(deptID)){
                queryWrapper.eq("OWNING_DEPT", deptID);
            }
        }else if(BizzDepthEntry.DEEPDOWN.equals(de)){
            if(StrUtil.isNotBlank(deptID)){
                queryWrapper.eq("OWNING_DEPT", deptID);
            }else{
                queryWrapper.in("OWNING_DEPT", units.stream().map(unit -> unit.getIdentity().toString()).collect(Collectors.toList()));
            }
        }else{
            log.error("该用户在实体{}配置了错误的权限{}", NICHE_CODE, de);
        }
        // 根据条件查询商机列表
        List<TRbshangji4DTO> deptValue = rbShangjiMapper.selectList(queryWrapper);
        // 当前年份
        int nowYear = DateUtil.year(new Date());
        // 排除 商机输单 且最后修改日期是 不是当前年份
        List<TRbshangji4DTO> loseList = deptValue.
                stream().
                filter(
                        ca -> NicheWinRate.loseCase().contains(ca.getShangjijieduanyinglv())
                ).
                filter(
                        ca ->  nowYear != DateUtil.year(ca.getModifiedOn())
                ).
                collect(Collectors.toList());
        // 排除 商机赢单 且预计日期是 不是当前年份
        List<TRbshangji4DTO> winList = deptValue.
                stream().
                filter(
                        ca -> NicheWinRate.winCase().contains(ca.getShangjijieduanyinglv())
                ).
                filter(
                        ca ->  (Objects.nonNull(ca.getShangjiyingdanshijian()) && nowYear != DateUtil.year(ca.getShangjiyingdanshijian())) || Objects.isNull(ca.getShangjiyingdanshijian())
                ).
                collect(Collectors.toList());
        deptValue.removeAll(loseList);
        deptValue.removeAll(winList);
        // 商机列表根据所属部门分组
        Map<String, List<TRbshangji4DTO>> deptMaps  = deptValue.stream().collect(Collectors.groupingBy(TRbshangji4DTO::getOwningUser, Collectors.toList()));
        // 清洗个人数据
        List<NicheStatisticsVO> result = getNicheStatisticsVOS(deptMaps);
        // 个人数据按照赢单商机金额降序、签约转化率降序、赢率60%-90%商机金额降序、部门降序排列
        result = result.
                stream().
                sorted(Comparator.comparing(NicheStatisticsVO::getWinNicheAmount, Comparator.reverseOrder()).
                        thenComparing(NicheStatisticsVO::getConversionRate, Comparator.reverseOrder()).
                        thenComparing(NicheStatisticsVO::getNicheAmountWinRate60_90, Comparator.reverseOrder()).
                        thenComparing(NicheStatisticsVO::getOwnerDept, Comparator.reverseOrder())
                ).
                collect(Collectors.toList());
        return new ReturnT(result);
    }

    @NotNull
    private List<NicheStatisticsVO> getNicheStatisticsVOS(Map<String, List<TRbshangji4DTO>> map) {
        List<NicheStatisticsVO> statistics = new ArrayList<>();
        for(Map.Entry<String, List<TRbshangji4DTO>> entry : map.entrySet()){
            List<TRbshangji4DTO> values = entry.getValue();
            // 部门id
            String deptId = values.get(0).getOwningDept();
            String userId = values.get(0).getOwningUser();
            NicheStatisticsVO vo = new NicheStatisticsVO();
            // 反编译查询商机所在的部门名称呢
            try {
                Department department = Application.getUserStore().getDepartment(ID.valueOf(deptId));
                vo.setOwnerDept(department.getName());
                vo.setOwnerDeptId(department.getIdentity().toString());
                vo.setParentDeptId(department.getParent() == null? "": department.getParent().getIdentity().toString());
            }catch (Exception e){
                e.printStackTrace();
            }
            // 反编译查询商机所在的所属用户名称呢
            try {
                User user = Application.getUserStore().getUser(ID.valueOf(userId));
                vo.setOwner(user.getFullName());
                vo.setOwnerId(user.getId().toString());
            }catch (NoMemberFoundException e){
                e.printStackTrace();
            }

            vo.setNicheNumber(values.size());
            // 赢单商机列表
            List<TRbshangji4DTO> winList = values.stream().filter(ca -> NicheWinRate.winCase().contains(ca.getShangjijieduanyinglv())).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(winList)){
                vo.setWinNicheNumber(winList.size());
                vo.setWinNicheAmount(winList.stream().map(TRbshangji4DTO::getShangjijineyuan).map(item -> item.setScale(2, RoundingMode.HALF_UP)).reduce(BigDecimal.ZERO,BigDecimal::add));
            }
            // 输单商机列表
            List<TRbshangji4DTO> loseList = values.stream().filter(ca -> NicheWinRate.loseCase().contains(ca.getShangjijieduanyinglv())).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(loseList)){
                vo.setLooseNicheNumber(loseList.size());
                vo.setLooseNicheAmount(loseList.stream().map(TRbshangji4DTO::getShangjijineyuan).map(item -> item.setScale(2, RoundingMode.HALF_UP)).reduce(BigDecimal.ZERO,BigDecimal::add));
            }
            // 赢率10%-50%商机列表
            List<TRbshangji4DTO> case10_50List = values.stream().filter(ca -> NicheWinRate.case10_50().contains(ca.getShangjijieduanyinglv())).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(case10_50List)){
                vo.setNicheNumberWinRate10_50(case10_50List.size());
                vo.setNicheAmountWinRate10_50(case10_50List.stream().map(TRbshangji4DTO::getShangjijineyuan).map(item -> item.setScale(2, RoundingMode.HALF_UP)).reduce(BigDecimal.ZERO,BigDecimal::add));
            }
            // 赢率60%-90%商机列表
            List<TRbshangji4DTO> case60_90List = values.stream().filter(ca -> NicheWinRate.case60_90().contains(ca.getShangjijieduanyinglv())).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(case60_90List)){
                vo.setNicheNumberWinRate60_90(case60_90List.size());
                vo.setNicheAmountWinRate60_90(case60_90List.stream().map(TRbshangji4DTO::getShangjijineyuan).map(item -> item.setScale(2, RoundingMode.HALF_UP)).reduce(BigDecimal.ZERO,BigDecimal::add));
            }
            vo.countAmount();
            statistics.add(vo);
        }
        return statistics;
    }

    @PostMapping("/payCollectionStatus")
    public Map<String, Object> payCollectionStatus(HttpServletRequest request) {
        Map<String, Object> result = new HashMap<>();
        final ID userId = getRequestUser(request);
        User user = Application.getUserStore().getUser(userId);
        Role role = user.getOwningRole();
        Privileges ep = role.getPrivileges(CONTACT_CODE);
        log.info("当前用户{}对合同的权限：{}", userId, JSONObject.toJSONString(ep));
        DepthEntry de = ep.superlative(BizzPermission.READ);
        log.info("当前用户{}对合同的读取权限：{}", userId, JSONObject.toJSONString(de));
        // 当前用户所在部门
        Department dept = UserHelper.getDepartment(userId);
        // 查询该组织下的所有商机统计信息
        QueryWrapper<TRbhetong0DTO> queryWrapper = new QueryWrapper<>();
        if(BizzDepthEntry.PRIVATE.equals(de)){
            queryWrapper.eq("OWNING_USER", userId.toString());
        }else if(BizzDepthEntry.LOCAL.equals(de)){
            queryWrapper.eq("OWNING_DEPT", dept.getIdentity().toString());
        }else if(userId.equals(UserService.ADMIN_USER)  || BizzDepthEntry.GLOBAL.equals(de)){
        }else if(BizzDepthEntry.DEEPDOWN.equals(de)){
            // 坐在部门的所有子部门
            Set<BusinessUnit> units = dept.getAllChildrenModified();
            units.add(dept);
            queryWrapper.in("OWNING_DEPT", units.stream().map(unit -> unit.getIdentity().toString()).collect(Collectors.toList()));
        }else{
            log.error("该用户在实体{}配置了错误的权限{}", NICHE_CODE, de);
        }
        // 根据条件查询合同列表
        List<TRbhetong0DTO> contractList = tRbhetong0Mapper.selectList(queryWrapper);
        if(CollectionUtil.isNotEmpty(contractList)){
            // 批量查询合同的回款计划
            QueryWrapper<THuikuanjihuaDTO> huikuanjihuaWrapper = new QueryWrapper<>();
            huikuanjihuaWrapper.in("GUANLIANHETONG", contractList.stream().map(TRbhetong0DTO::getRbhetong0Id).collect(Collectors.toList()));
            List<THuikuanjihuaDTO> huikuanjihuaList = tHuikuanjihuaMapper.selectList(huikuanjihuaWrapper);
            // 批量查询合同的回款单
            QueryWrapper<TRbhuikuandanDTO> huikuandanWrapper = new QueryWrapper<>();
            huikuandanWrapper.in("HUIKUANJIHUA_ID", huikuanjihuaList.stream().map(THuikuanjihuaDTO::getHuikuanjihuaId).collect(Collectors.toList()));
            List<TRbhuikuandanDTO> huikuandanList = tHuikuandanMapper.selectList(huikuandanWrapper);
            // 批量查询已开票记录
            QueryWrapper<TKaipiaoguanliDTO> kaipiaoWrapper = new QueryWrapper<>();
            huikuandanWrapper.in("GUANLIANHUIKUANJIHUA", huikuanjihuaList.stream().map(THuikuanjihuaDTO::getHuikuanjihuaId).collect(Collectors.toList()));
            List<TKaipiaoguanliDTO> kaipiaoList = tKaipiaoguanliMapper.selectList(kaipiaoWrapper);

            List<FinancialStatisticsVO> statisticsVOS = new ArrayList<>();
            for(TRbhetong0DTO contract : contractList){
                FinancialStatisticsVO statisticsVO = new FinancialStatisticsVO(contract,
                        huikuanjihuaList.stream().filter(jh -> contract.getRbhetong0Id().equals(jh.getGuanlianhetong())).collect(Collectors.toList()));
                // 回款计划ID集合
                List<String> huikuanjihuaIds = statisticsVO.getHuikuanjihuaList().stream().map(THuikuanjihuaDTO::getHuikuanjihuaId).collect(Collectors.toList());
//                // 回款单集合
//                statisticsVO.setHuikuandanList(huikuandanList.stream().filter(ca -> huikuanjihuaIds.contains(ca.getHuikuanjihuaId())).collect(Collectors.toList()));
//                // 开票集合
//                statisticsVO.setKaipiaoList(kaipiaoList.stream().filter(ca -> huikuanjihuaIds.contains(ca.getGuanlianhuikuanjihua())).collect(Collectors.toList()));
                // 过滤没有全部回款 或者没有签约时间的合同 或者签约时间是2000以前的
                if(Objects.nonNull(contract.getHetongshengxiaoriqi())
                        && DateUtil.year(contract.getHetongshengxiaoriqi()) > 2000){
                    statisticsVOS.add(statisticsVO);
                }else{
                    log.info("->{}不符合标准，不予统计-->{}.", statisticsVO.getContract().getRbhetong0Id(), statisticsVO.getHuikuanjihuaList());
                }
            }
            result.put("year", byYear(statisticsVOS));
            result.put("history", byHistory(statisticsVOS, huikuandanList, kaipiaoList));
            result.put("dept", byDept(statisticsVOS));
            result.put("person", byPerson(statisticsVOS));
            result.put("customer", byCustomer(statisticsVOS));
        }
        return result;
    }

    private JSONArray byPerson(List<FinancialStatisticsVO> statisticsVOS) {
        Map<String, Map<String, BigDecimal>> result = new HashMap<>();
        // 合同按照所属人分组
        Map<String, List<FinancialStatisticsVO>> personMaps = statisticsVOS.stream().collect(Collectors.groupingBy(FinancialStatisticsVO::getOwningUserName, Collectors.toList()));
        for(Map.Entry<String, List<FinancialStatisticsVO>> entry : personMaps.entrySet()){
            String person = entry.getKey();
            log.info("统计了{}{}个合同的数据", person, entry.getValue().size());
            entry.getValue().stream().forEach(ca -> log.info("{}签约的合同{}应收未收金额{}", person, ca.getContract().getHetongbianhao(), ca.getYingshouweishoujine()));
            Map<String, BigDecimal> countMap = tt(entry.getValue());
            countMap.put("rate", NumberUtil.div(NumberUtil.mul(countMap.get("yikaipiaoweihuikuanjine"), 100), NumberUtil.equals(NumberUtil.null2Zero(countMap.get("jihuahuikuanjine")), BigDecimal.ZERO) ? BigDecimal.ONE : countMap.get("jihuahuikuanjine"), 4));

            result.put(person, countMap);
        }
        // map排序
        TreeMap<String, Map<String, BigDecimal>> treeSet = MapUtil.sort(result);
        JSONArray array = getObjects(treeSet);
        return array;
    }

    private JSONArray byCustomer(List<FinancialStatisticsVO> statisticsVOS) {
        Map<String, Map<String, BigDecimal>> result = new HashMap<>();
        // 合同按照所属人分组
        Map<String, List<FinancialStatisticsVO>> customerMaps = statisticsVOS.stream().collect(Collectors.groupingBy(FinancialStatisticsVO::getCustomerName, Collectors.toList()));
        for(Map.Entry<String, List<FinancialStatisticsVO>> entry : customerMaps.entrySet()){
            String person = entry.getKey();
            Map<String, BigDecimal> countMap = tt(entry.getValue());
            countMap.put("rate", NumberUtil.div(NumberUtil.mul(countMap.get("yikaipiaoweihuikuanjine"), 100), NumberUtil.equals(NumberUtil.null2Zero(countMap.get("jihuahuikuanjine")), BigDecimal.ZERO) ? BigDecimal.ONE : countMap.get("jihuahuikuanjine"), 4));
            result.put(person, countMap);
        }
        // map排序
        TreeMap<String, Map<String, BigDecimal>> treeSet = MapUtil.sort(result);
        JSONArray array = getObjects(treeSet);
        return array;
    }


    /**
     * 按年度分析应收未收情况
     * @param statisticsVOS
     * @return
     */
    private JSONArray byYear(List<FinancialStatisticsVO> statisticsVOS) {
        Map<String, Map<String, BigDecimal>> result = new HashMap<>();
        // 合同按照年度分组
        Map<String, List<FinancialStatisticsVO>> yearMaps = new HashMap<>();
        // 将合同按照签约时间（年份）分组
        for(FinancialStatisticsVO statisticsVO : statisticsVOS){
            String makeDateStr = DateUtil.year(statisticsVO.getQianyueshijian()) + "";
            List<FinancialStatisticsVO> contracts = yearMaps.containsKey(makeDateStr) ? yearMaps.get(makeDateStr) : new ArrayList<>();
            contracts.add(statisticsVO);
            yearMaps.put(makeDateStr, contracts);
        }
        for(Map.Entry<String, List<FinancialStatisticsVO>> entry : yearMaps.entrySet()){
            String year = entry.getKey();
            Map<String, BigDecimal> countMap = tt(entry.getValue());
            result.put(year, countMap);
        }
        // map排序
        TreeMap<String, Map<String, BigDecimal>> treeSet = MapUtil.sort(result);
        JSONArray array = getObjects(treeSet);
        return array;
    }
    private JSONArray byHistory(List<FinancialStatisticsVO> statisticsVOS, List<TRbhuikuandanDTO> huikuandanList, List<TKaipiaoguanliDTO> kaipiaoList) {
//        // 深度复制
//        List<FinancialStatisticsVO> temp = Lists.newArrayList();
//        CollectionUtil.addAll(temp, new Object[statisticsVOS.size()]);
//        Collections.copy(temp, statisticsVOS);
        // 合并全部的回款计划
        List<THuikuanjihuaDTO> huikuanjihuaList = new ArrayList<>();
        for(FinancialStatisticsVO value : statisticsVOS){
            huikuanjihuaList.addAll(value.getHuikuanjihuaList());
        }
        // 当前年份
        int nowYear = DateUtil.year(new Date());
        int nowMonth = DateUtil.month(new Date());
        Map<String, Map<String, BigDecimal>> result = new HashMap<>();
        // 过滤本月回款计划
        List<THuikuanjihuaDTO> monthData = huikuanjihuaList.stream().
                filter(statistics -> nowYear == DateUtil.year(statistics.getYujihuikuanriqi()) &&
                        nowMonth == DateUtil.month(statistics.getYujihuikuanriqi()))
                .collect(Collectors.toList());
        huikuandanList.forEach(hk -> log.info("----->有效回款单编号：{}", hk.getHuikuandanbianhao()));
        // 过滤本月回款单
        List<TRbhuikuandanDTO> monthDanData = huikuandanList.stream().
                filter(statistics -> Objects.nonNull(statistics.getHuikuanriqi())).
                filter(statistics -> nowYear == DateUtil.year(statistics.getHuikuanriqi()) &&
                        nowMonth == DateUtil.month(statistics.getHuikuanriqi()))
                .collect(Collectors.toList());
        // 过滤本月回款计划的开票记录
        List<TKaipiaoguanliDTO> monthKPData = kaipiaoList.stream().
                filter(ca -> nowYear == DateUtil.year(ca.getCreatedOn()) &&
                nowMonth == DateUtil.month(ca.getCreatedOn()))
                .collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(monthData)){
            List<THuikuanjihuaDTO> thisMonth = monthData;
            thisMonth.forEach(ca -> log.info("本月的回款计划：->{}", ca.getHuikuanjihuaName()));

            abc(monthDanData, monthKPData, thisMonth, result, "month");

            huikuanjihuaList.removeAll(monthData);
            huikuandanList.removeAll(monthDanData);
            kaipiaoList.removeAll(monthKPData);
        }
        // 过滤本年度历史月份（即不包含当前月份）
        List<THuikuanjihuaDTO> yearData = huikuanjihuaList.stream().filter(ca -> nowYear == DateUtil.year(ca.getYujihuikuanriqi())).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(yearData)){
            // 过滤本年回款单
            List<TRbhuikuandanDTO> yearDanData = huikuandanList.stream().
                    filter(statistics -> Objects.nonNull(statistics.getHuikuanriqi())).
                    filter(statistics -> nowYear == DateUtil.year(statistics.getHuikuanriqi()))
                    .collect(Collectors.toList());
            // 过滤本年回款计划的开票记录
            List<TKaipiaoguanliDTO> yearKPData = kaipiaoList.stream().
                    filter(ca -> nowYear == DateUtil.year(ca.getCreatedOn()))
                    .collect(Collectors.toList());
            abc(yearDanData, yearKPData, yearData, result, "year");
            huikuanjihuaList.removeAll(yearData);
            huikuandanList.removeAll(yearDanData);
            kaipiaoList.removeAll(yearKPData);
        }
        abc(huikuandanList, kaipiaoList, huikuanjihuaList, result, "history");
        // map排序
        TreeMap<String, Map<String, BigDecimal>> treeSet = MapUtil.sort(result);
        JSONArray array = getObjects(treeSet);
        return array;
    }


    /**
     * 按照部门分析
     * @param statisticsVOS
     * @return
     */
    private JSONArray byDept(List<FinancialStatisticsVO> statisticsVOS) {
        Map<String, Map<String, BigDecimal>> result = new HashMap<>();
        statisticsVOS.stream().filter(ca -> ca.getOwningDeptName().contains("北京")).forEach(ca -> log.info("签约合同{}", ca.getContract().getRbhetong0Id()));
        // 合同按照所属部门分组
        Map<String, List<FinancialStatisticsVO>> deptMaps = statisticsVOS.stream().collect(Collectors.groupingBy(FinancialStatisticsVO::getOwningDeptName, Collectors.toList()));
        for(Map.Entry<String, List<FinancialStatisticsVO>> entry : deptMaps.entrySet()){
            String deptId = entry.getKey();
            List<FinancialStatisticsVO> values = entry.getValue();
            Map<String, BigDecimal> countMap = tt(entry.getValue());
            // 合并收款计划
            List<THuikuanjihuaDTO> jihuaList = Lists.newArrayList();
            for(FinancialStatisticsVO statistics : values){
                jihuaList.addAll(statistics.getHuikuanjihuaList());
            }
            log.info("{}部门统计了{}个合同的数据", deptId, values.size());
            // 统计超过三个月应收未收
            BigDecimal chaoThreeMonthYingshouWeishou =  jihuaList.stream().
                            // 过滤计划收款金额 大于 实际收款金额的记录
                            filter(ca -> NumberUtil.isGreater(ca.getJihuashoukuanjine(), ca.getShijishoukuanjine())).
                            // 过滤预计收款日期早于当前日期三个月的记录
                            filter(ca -> DateUtil.compare(DateUtil.offsetMonth(ca.getYujihuikuanriqi(), 3), new Date()) < 0).
                            // 统计应收未收的合计
                            map(ca -> NumberUtil.sub(ca.getJihuashoukuanjine(), ca.getShijishoukuanjine())).
                            reduce(BigDecimal.ZERO, BigDecimal::add);
            // 统计三个月内应收未收
            BigDecimal inThreeMonthYingshouWeishou =  jihuaList.stream().
                            // 过滤计划收款金额 大于 实际收款金额的记录
                            filter(ca -> NumberUtil.isGreater(ca.getJihuashoukuanjine(), ca.getShijishoukuanjine())).
                            // 过滤预计收款日期早于当前日期
                            filter(ca -> DateUtil.compare(ca.getYujihuikuanriqi(), new Date()) <= 0).
                            // 过滤预计收款日期早于当前日期三个月的记录
                            filter(ca -> DateUtil.compare(DateUtil.offsetMonth(ca.getYujihuikuanriqi(), 3), new Date()) >= 0).
                            // 统计应收未收的合计
                            map(ca -> NumberUtil.sub(ca.getJihuashoukuanjine(), ca.getShijishoukuanjine())).
                            reduce(BigDecimal.ZERO, BigDecimal::add);
            // 过滤本年度当前月份数据
            List<THuikuanjihuaDTO> huikuanjihuaList = new ArrayList<>();
            for(FinancialStatisticsVO value : values){
                huikuanjihuaList.addAll(value.getHuikuanjihuaList());
            }
            BigDecimal monthData = huikuanjihuaList.stream().filter(ca -> DateUtil.year(new Date()) == DateUtil.year(ca.getYujihuikuanriqi()) &&
                            DateUtil.month(new Date()) == DateUtil.month(ca.getYujihuikuanriqi())).
                    map(ca -> ca.getJihuashoukuanjine()).
                    reduce(BigDecimal.ZERO, BigDecimal::add);
            countMap.put("overThreeMonth", chaoThreeMonthYingshouWeishou);
            countMap.put("inThreeMonth", inThreeMonthYingshouWeishou);
            countMap.put("month", monthData);
            result.put(deptId, countMap);
        }
        // map排序
        TreeMap<String, Map<String, BigDecimal>> treeSet = MapUtil.sort(result);
        JSONArray array = getObjects(treeSet);
        return array;
    }

    /**
     * map转数组，并把当时的key作为值写入
     * @param treeSet
     * @return
     */
    @NotNull
    private JSONArray getObjects(TreeMap<String, Map<String, BigDecimal>> treeSet) {
        JSONArray array = new JSONArray();
        for (String key : treeSet.keySet()) {
            Map<String, BigDecimal> value = treeSet.get(key);
            JSONObject item = JSONObject.parseObject(JSONObject.toJSONString(value));
            item.put("key", key);
            array.add(item);
        }
        return array;
    }

    @NotNull
    private Map<String, BigDecimal> tt(List<FinancialStatisticsVO> statisticsVOList) {
        Map<String, BigDecimal> countMap = new HashMap<>();
        countMap.put("total", statisticsVOList.stream().map(FinancialStatisticsVO::getQianyuejine).reduce(BigDecimal.ZERO, BigDecimal::add));
        countMap.put("weishoujine", statisticsVOList.stream().map(FinancialStatisticsVO::getWeishoujine).reduce(BigDecimal.ZERO, BigDecimal::add));
        countMap.put("yihuikuanjine", statisticsVOList.stream().map(FinancialStatisticsVO::getYihuikuanjine).reduce(BigDecimal.ZERO, BigDecimal::add));
        countMap.put("jihuahuikuanjine", statisticsVOList.stream().map(FinancialStatisticsVO::getJihuahuikuanjine).reduce(BigDecimal.ZERO, BigDecimal::add));
        countMap.put("yingshouweishoujine", statisticsVOList.stream().map(FinancialStatisticsVO::getYingshouweishoujine).reduce(BigDecimal.ZERO, BigDecimal::add));
        countMap.put("yikaipiaoweihuikuanjine", statisticsVOList.stream().map(FinancialStatisticsVO::getYikaipiaoweihuikuanjine).reduce(BigDecimal.ZERO, BigDecimal::add));
        return countMap;
    }

    /**
     *
     * @param huikuandanList 回款单列表
     * @param kaipiaoList 开票记录列表
     * @param huikuanjihuaList 回款计划列表
     * @param result
     * @param history
     */
    private void abc(List<TRbhuikuandanDTO> huikuandanList, List<TKaipiaoguanliDTO> kaipiaoList, List<THuikuanjihuaDTO> huikuanjihuaList, Map<String, Map<String, BigDecimal>> result, String history) {
        // 历史数据
        Map<String, BigDecimal> countMap = new HashMap<>();
        // 本年回款金额-根据回款单统计
        BigDecimal yihuikuanjine = huikuandanList.stream().map(TRbhuikuandanDTO::getHuikuanjine).reduce(BigDecimal.ZERO, BigDecimal::add);
        countMap.put("yihuikuanjine", yihuikuanjine);
        // 本年应回款金额-根据回款计划统计
        BigDecimal jihuahuikuanjine = huikuanjihuaList.stream().map(THuikuanjihuaDTO::getJihuashoukuanjine).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 本年实际回款金额-根据回款计划统计
        BigDecimal shijihuikuanjine = huikuanjihuaList.stream().map(THuikuanjihuaDTO::getShijishoukuanjine).reduce(BigDecimal.ZERO, BigDecimal::add);
        countMap.put("jihuahuikuanjine", jihuahuikuanjine);
        countMap.put("yingshouweishoujine", NumberUtil.sub(jihuahuikuanjine, shijihuikuanjine));
        // 本年已开票金额-根据创建时间统计
        BigDecimal yikaipiaojine = kaipiaoList.stream().map(TKaipiaoguanliDTO::getKaipiaojine).reduce(BigDecimal.ZERO, BigDecimal::add);
        countMap.put("yikaipiaoweihuikuanjine", NumberUtil.sub(yikaipiaojine, shijihuikuanjine));

        result.put(history, countMap);
    }
}
